package com.personalkeeper;

import java.util.Collection;
import java.util.Date;

import com.personalkeeper.HistoryProvider.LocationHistory;
import com.personalkeeper.HistoryProvider.Markers;
import com.personalkeeper.HistoryProvider.Notes;
import com.personalkeeper.HistoryProvider.Statistics;
import com.personalkeeper.HistoryProvider.TrackingSession;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import static com.personalkeeper.PersonalKeeper.*;

public class DatabaseWriter {

    private static final String TAG = DatabaseWriter.class.toString();

    public static class Note {

        private String mTitle;
        private String mDescription;
        private Location mLocation;
        private String mImagePath;

        public Note() {

        }

        public Note(String title, String description, Location location, String imagePath) {
            mTitle = title;
            mDescription = description;
            mLocation = location;
            mImagePath = imagePath;
        }

        public String getImagePath() {
            return mImagePath;
        }

        public void setImagePath(String imagePath) {
            this.mImagePath = imagePath;
        }

        public String getTitle() {
            return mTitle;
        }

        public void setTitle(String title) {
            this.mTitle = title;
        }

        public String getDescription() {
            return mDescription;
        }

        public void setDescription(String description) {
            this.mDescription = description;
        }

        public Location getLocation() {
            return mLocation;
        }

        public void setLocation(Location location) {
            this.mLocation = location;
        }
    }

    public static class Marker {

        private String mName;
        private double mLatitude;
        private double mLongitude;
        private String mAddress;
        private Date mDate;
        private boolean mRequest;

        public Marker() {
        }

        public Marker(String name, double latitude, double longitude, String address,
                      Date date) {
            mName = name;
            mLatitude = latitude;
            mLongitude = longitude;
            mAddress = address;
            mDate = date;
        }

        public static Marker fromBundle(Bundle bundle) {
            if (bundle.containsKey(LATITUDE) &&
                    bundle.containsKey(LONGITUDE) &&
                    bundle.containsKey(DATE)) {
                try {
                    Marker retval = new Marker();
                    retval.setName(bundle.getString(NAME));
                    retval.setAddress(bundle.getString(ADDRESS));
                    retval.setLatitude(bundle.getDouble(LATITUDE));
                    retval.setLongitude(bundle.getDouble(LONGITUDE));
                    retval.setDate(new Date(bundle.getLong(DATE)));
                    retval.setRequest(bundle.getBoolean(REQUEST));
                    return retval;
                } catch (ClassCastException e) {
                    Log.d(TAG, "bad bundle");
                    e.printStackTrace();
                    return null;
                }
            } else
                return null;
        }

        public String getName() {
            return mName;
        }

        public void setName(String name) {
            this.mName = name;
        }

        public double getLatitude() {
            return mLatitude;
        }

        public void setLatitude(double latitude) {
            mLatitude = latitude;
        }

        public double getLongitude() {
            return mLongitude;
        }

        public void setLongitude(double longitude) {
            mLongitude = longitude;
        }

        public String getAddress() {
            return mAddress;
        }
        public void setAddress(String address) {
            this.mAddress = address;
        }

        public Date getDate() {
            return mDate;
        }

        public void setDate(Date date) {
            mDate = date;
        }
        
        public void setRequest(boolean value) {
            mRequest = value;
        }
        
        public boolean getRequest() {
            return mRequest;
        }
    }

    @Deprecated
    public static class StatisticsRecord {
        public enum Type { MONTHLY, DAILY };

        private Type mType;
        private Date mDate;
        private double mDistance;

        public StatisticsRecord(Type type, Date date, double distance) {
            mType = type;
            mDate = date;
            mDistance = distance;
        }

        public Type getType() {
            return mType;
        }

        public Date getDate() {
            return mDate;
        }

        public double getDistance() {
            return mDistance;
        }
    }

    public static class Session {

        private Date mStartTime;
        private Date mEndTime;
        private double mDistance;

        public Session(Date start, Date end, double distance) {
            mStartTime = start;
            mEndTime = end;
            mDistance = distance;
        }

        public Date getStartTime() {
            return mStartTime;
        }
        public Date getEndTime() {
            return mEndTime;
        }
        public double getDistance() {
            return mDistance;
        }
    }

    private final ContentResolver mCr;

    public DatabaseWriter(Context context) {
        mCr = context.getContentResolver();
    }

    public int insert(Collection<Location> locations) {
        ContentValues[] items = new ContentValues[locations.size()];
        int i = 0;
        for (Location location : locations) {
            items[i] = contentValuesFromLocation(location);
            i++;
        }

        return mCr.bulkInsert(LocationHistory.CONTENT_URI, items);
    }
    public Uri insert(Location location) {
        ContentValues values = new ContentValues();
        values.put(LocationHistory.LATITUDE,  location.getLatitude());
        values.put(LocationHistory.LONGITUDE, location.getLongitude());
        values.put(LocationHistory.DATE,      location.getTime());

        return mCr.insert(LocationHistory.CONTENT_URI, values);
    }
    public Uri insert(Note note) {
        ContentValues values = new ContentValues();
        values.put(Notes.TITLE,       note.getTitle());
        values.put(Notes.DESCRIPTION, note.getDescription());
        values.put(Notes.LATITUDE,    note.getLocation().getLatitude());
        values.put(Notes.LONGITUDE,   note.getLocation().getLongitude());
        values.put(Notes.DATE,        note.getLocation().getTime());
        values.put(Notes.IMAGE_PATH,  note.getImagePath());

        return mCr.insert(Notes.CONTENT_URI, values);
    }
    public Uri insert(Marker marker) {
        ContentValues values = new ContentValues();
        values.put(Markers.NAME,         marker.getName());
        values.put(Markers.LATITUDE,     marker.getLatitude());
        values.put(Markers.LONGITUDE,    marker.getLongitude());
        values.put(Markers.DATE,         marker.getDate().getTime());
        values.put(Markers.ADDRESS,      marker.getAddress());
        values.put(Markers.REQUEST,      marker.getRequest() ? 1 : 0);

        return mCr.insert(Markers.CONTENT_URI, values);
    }
    public Uri insert(StatisticsRecord record) {
        ContentValues values = new ContentValues();
        values.put(Statistics.TYPE, record.getType().toString());
        values.put(Statistics.DATE, record.getDate().getTime());
        values.put(Statistics.DISTANCE, record.getDistance());

        return mCr.insert(Statistics.CONTENT_URI, values);
    }
    public Uri insert(Session session) {
        ContentValues values = new ContentValues();
        values.put(TrackingSession.START_DATE, session.getStartTime().getTime());
        values.put(TrackingSession.END_DATE, session.getEndTime().getTime());
        values.put(TrackingSession.DISTANCE, session.getDistance());

        return mCr.insert(TrackingSession.CONTENT_URI, values);
    }


    private static ContentValues contentValuesFromLocation(Location location) {
        ContentValues values = new ContentValues();
        values.put(LocationHistory.LATITUDE,  location.getLatitude());
        values.put(LocationHistory.LONGITUDE, location.getLongitude());
        values.put(LocationHistory.DATE,      location.getTime());

        return values;
    }
}